var hypertopic = {	
	_colors : new Array("hsl(220,62%,74%)", "hsl(44,100%,73%)", "hsl(81,32%,71%)", "hsl(359,73%,78%)", "hsl(260,50%,77%)"),
	colorIndex: 0,
	NS_XHTML : 'http://www.w3.org/1999/xhtml',
	MARK_SELECTION_START : '\u200B\u200B\u200B\u200B\u200B',
	MARK_SELECTION_END : '\u200B\u200B\u200B\u200B\u200B\u200B\u200B',
	// MARK_SELECTION_START : '[[[[',
	// MARK_SELECTION_END : ']]]]',
	
	init: function(){
		//alert('init');
		//this.highlightSelection(0, 4, 0);
		fragment.loadFragement();
		for(i = fragment.fragments.length-1; i >=0 ; i--){
			this.highlightSelection(fragment.fragments[i][0], fragment.fragments[i][1], fragment.fragments[i][2]);
		}
	},
	
	clickButton: function(){
		var pos = this.getSelectionPos();
		var info_debug = document.getElementById('info_debug');
		info_debug.innerHTML = "selection range: " + pos[0] + "+" + pos[1] + "&nbsp;&nbsp;&nbsp;(color:"+hypertopic.colorIndex + ")";
		if(!fragment.validSelection(pos[0], pos[1])){
			alert('Error: you cannot create fragment here!');
			return false;
		}
		var len = this.highlightSelection(pos[0], pos[1], hypertopic.colorIndex);
		fragment.addFragment(pos[0], pos[1], hypertopic.colorIndex, len);
	},
	
	setColor: function(colorIndex){
		//alert(colorIndex);
		for (var i = 0; i < hypertopic._colors.length; i++)
		{
			var n = document.getElementById('highlight_color_' + i);
			if(i == colorIndex){
				hypertopic.colorIndex = i;
				n.innerHTML = '√';
				n.style.border="1px solid #000000;";
			}else
			{
				n.innerHTML = '';
				n.style.border = "1px dotted #000000;";
			}
		}
	},
	
	highlightSelection: function(startPos, endPos, colorIndex){
		var startTag = '<hypertopic_fragment id="' + startPos + '+' + endPos +'">';
		var doc = document.documentElement;
		var docHtml = document.documentElement.innerHTML;
		//var docStr = (new XMLSerializer()).serializeToString(doc);
		var selectionHtml = docHtml.substr(startPos, endPos-startPos);
		var highLightHTML = this.highLightByIndexOf(selectionHtml, colorIndex);
		
		var endHtml = docHtml.substr(endPos);
		var startHtml = docHtml.substr(0, startPos);
		//alert(colorIndex);
		
		//this.debug(highLightHTML);
		document.documentElement.innerHTML = startHtml + highLightHTML + endHtml;
		return highLightHTML.length;
	},
	
	attachAnchor: function(anchorId, str){
		return "<a name='"+ anchorId + "'> </a>" + str;
	},
	
	getSelectionPos: function() {
		var selection = window.getSelection(); 
		var range = selection.getRangeAt(0); 
		var startContainer = range.startContainer; 
		var endContainer = range.endContainer;
		var startOffset = range.startOffset; 
		var endOffset = range.endOffset; 
		var ancestorContainer = range.commonAncestorContainer;
		
		var doc = ancestorContainer.ownerDocument; 
		// let the ancestor be an element 
		if (ancestorContainer.nodeType == Node.TEXT_NODE || ancestorContainer.nodeType == Node.CDATA_SECTION_NODE) 
			ancestorContainer = ancestorContainer.parentNode;
		
		// for selectAll, let's use the entire document, including <html>...</html> 
		// @see DocumentViewerImpl::SelectAll() for how selectAll is implemented 
		try { 
				if(ancestorContainer == doc.body) 
					ancestorContainer = doc.documentElement; 
		} catch (e) { } 
		var startPath = this.getPath(ancestorContainer, startContainer); 
		var endPath = this.getPath(ancestorContainer, endContainer);
		var oldAncestorContainer = ancestorContainer;
		ancestorContainer = ancestorContainer.cloneNode(true);
		startContainer = ancestorContainer;
		endContainer = ancestorContainer;
		var canDrawSelection = ancestorContainer.hasChildNodes();
		if (canDrawSelection)
		{
				var i;
				for (i = startPath ? startPath.length - 1: - 1; i >= 0; i--)
				{
						startContainer = startContainer.childNodes.item(startPath[i]);
				}
				for (i = endPath ? endPath.length - 1: - 1; i >= 0; i--)
				{
						endContainer = endContainer.childNodes.item(endPath[i]);
				}
				var tmpNode;
				if (endContainer.nodeType == Node.TEXT_NODE || endContainer.nodeType ==
						Node.CDATA_SECTION_NODE)
				{
						if ((endOffset > 0 && endOffset < endContainer.data.length) ||
								!endContainer.parentNode || !endContainer.parentNode.parentNode)
								endContainer.insertData(endOffset, this.MARK_SELECTION_END);
						else
						{
								tmpNode = doc.createTextNode(this.MARK_SELECTION_END);
								endContainer = endContainer.parentNode;
								if (endOffset == 0)
										endContainer.parentNode.insertBefore(tmpNode, endContainer);
								else
										endContainer.parentNode.insertBefore(tmpNode,
												endContainer.nextSibling);
						}
				}
				else
				{
						tmpNode = doc.createTextNode(this.MARK_SELECTION_END);
						endContainer.insertBefore(tmpNode, endContainer.childNodes.item
								(endOffset));
				}
				if (startContainer.nodeType == Node.TEXT_NODE ||
						startContainer.nodeType == Node.CDATA_SECTION_NODE)
				{
						if ((startOffset > 0 && startOffset < startContainer.data.length)
								|| !startContainer.parentNode ||
								!startContainer.parentNode.parentNode || startContainer !=
								startContainer.parentNode.lastChild)
								startContainer.insertData(startOffset,
										this.MARK_SELECTION_START);
						else
						{
								tmpNode = doc.createTextNode(this.MARK_SELECTION_START);
								startContainer = startContainer.parentNode;
								if (startOffset == 0)
										startContainer.parentNode.insertBefore(tmpNode,
												startContainer);
								else
										startContainer.parentNode.insertBefore(tmpNode,
												startContainer.nextSibling);
						}
				}
				else
				{
						tmpNode = doc.createTextNode(this.MARK_SELECTION_START);
						startContainer.insertBefore(tmpNode, startContainer.childNodes.item
								(startOffset));
				}
		}
		
		var oldParentNode = oldAncestorContainer.parentNode;
		oldParentNode.replaceChild(ancestorContainer, oldAncestorContainer);
		// tmpNode = doc.createElementNS(this.NS_XHTML, 'div');
		// 		tmpNode.appendChild(ancestorContainer);
		// 		var blockHTML = tmpNode.innerHTML;
		// 		blockHTML = blockHTML.substr(blockHTML.indexOf(this.MARK_SELECTION_START) + this.MARK_SELECTION_START.length);
		// 		blockHTML = blockHTML.substr(0, blockHTML.indexOf(this.MARK_SELECTION_END));
		// 		var startPos = doc.documentElement.innerHTML.indexOf(blockHTML);
		var docHtml = document.documentElement.innerHTML;
		var startPos = docHtml.indexOf(this.MARK_SELECTION_START);
		var endPos = docHtml.indexOf(this.MARK_SELECTION_END) - this.MARK_SELECTION_START.length;
		oldParentNode.replaceChild(oldAncestorContainer, ancestorContainer);
		
		var selectionPos = new Array(startPos, endPos);
		return selectionPos;
	},
	
	getPath: function(ancestor, node)
	{
			var n = node;
			var p = n.parentNode;
			if (n == ancestor || !p)
					return null;
			var path = new Array();
			if (!path)
					return null;
			do
			{
					for (var i = 0; i < p.childNodes.length; i++)
					{
							if (p.childNodes.item(i) == n)
							{
									path.push(i);
									break;
							}
					}
					n = p;
					p = n.parentNode;
			}
			while (n != ancestor && p);
			return path;
	},
	
	highLightByIndexOf: function(selectionText, colorIndex){
		highlightStartTag = "<font style='background-color:" + this._colors[colorIndex] + ";'>";
		highlightEndTag = "</font>";
		

		var result = "";
		var lcSelectionText = selectionText.toLowerCase();
		while(selectionText.length > 0){

			var startPos = selectionText.lastIndexOf("<");
			var endPos = selectionText.lastIndexOf(">");
			if (endPos >= startPos) {
				
				htmlTag = selectionText.substring(startPos, endPos + 1);
				if(htmlTag.toLowerCase().indexOf("/script") > 0){
					startPos = lcSelectionText.lastIndexOf("<script");
					endPos = lcSelectionText.lastIndexOf("/script>") + 9;
					htmlTag = selectionText.substring(startPos, endPos);
				}
				if(htmlTag.toLowerCase().indexOf("/textarea") > 0){
					startPos = lcSelectionText.lastIndexOf("<textarea");
					endPos = lcSelectionText.lastIndexOf("/textarea>") + 11;
					htmlTag = selectionText.substring(startPos, endPos);
				}
				if(selectionText.length > endPos+1)
							result = htmlTag + highlightStartTag + selectionText.substring(endPos + 1) + highlightEndTag + result;
						else
					result = htmlTag + result;
				selectionText = selectionText.substring(0, startPos);
						lcSelectionText = selectionText.toLowerCase();
					}
			else{
				if(startPos > 0)
					result = highlightStartTag + selectionText.substring(endPos+1, startPos) + highlightEndTag + selectionText.substring(startPos) + result;
				else
					result = highlightStartTag + selectionText.substring(endPos + 1) + highlightEndTag + result;
				selectionText = selectionText.substring(0, endPos+1);
						lcSelectionText = selectionText.toLowerCase();
			}
		}
		return result;
	},
	
	debug: function(str){
		var textarea_dump = document.createElement('textarea');
		textarea_dump.setAttribute("style", "width:100%; height:180px");
		textarea_dump.value=str;
		var body = document.getElementsByTagName('body');
				body[0].appendChild(textarea_dump);
	}
};



var fragment = {
	fragments : new Array(),
	
	validSelection: function(startPos, endPos){
		for(i=0; i < this.fragments.length; i++){
			if((startPos <= this.fragments[i][0] && endPos >= this.fragments[i][0])
				|| (startPos >= this.fragments[i][0] && endPos <= this.fragments[i][1])
				|| (startPos <= this.fragments[i][1] && endPos >= this.fragments[i][1]))
			{
				return false;
			}
		}
		return true;
	},
	
	addFragment: function(startPos, endPos, colorIndex, strLength){
		this.fragments.push(new Array(startPos, endPos, colorIndex, strLength));
		this.fragments.sortNum();
		this.saveFragment();
	},
	
	saveFragment: function(){
		var json = this.fragments.toJSON();
		util.setCookie('fragment', json);
	},
	
	loadFragement: function(){
		var json = util.getCookie('fragment');
		if(json != null)
		this.fragments = eval(json);
	}
};

var util = {
	getCookie : function( name ) {
		var start = document.cookie.indexOf( name + "=" );
		var len = start + name.length + 1;
		if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
			return null;
		}
		if ( start == -1 ) return null;
		var end = document.cookie.indexOf( ';', len );
		if ( end == -1 ) end = document.cookie.length;
		return unescape( document.cookie.substring( len, end ) );
	},

	setCookie: function( name, value, expires, path, domain, secure ) {
		var today = new Date();
		today.setTime( today.getTime() );
		if ( expires ) {
			expires = expires * 1000 * 60 * 60 * 24;
		}
		var expires_date = new Date( today.getTime() + (expires) );
		document.cookie = name+'='+escape( value ) +
			( ( expires ) ? ';expires='+expires_date.toGMTString() : '' ) + //expires.toGMTString()
			( ( path ) ? ';path=' + path : '' ) +
			( ( domain ) ? ';domain=' + domain : '' ) +
			( ( secure ) ? ';secure' : '' );
	},

	deleteCookie: function( name, path, domain ) {
		if ( getCookie( name ) ) document.cookie = name + '=' +
				( ( path ) ? ';path=' + path : '') +
				( ( domain ) ? ';domain=' + domain : '' ) +
				';expires=Thu, 01-Jan-1970 00:00:01 GMT';
	}
};

window.addEventListener('load', function(){ hypertopic.init(); }, true);